﻿using System;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace ThreeDContentPipeline
{
    public class ContentWriter : BinaryWriter
    {
        public ContentWriter(string file, ContentImporterContext context)
            : base(new FileStream(file, FileMode.Create))
        {
            Context = context;
        }

        public ContentImporterContext Context
        {
            get;
            private set;
        }

        public void Write(Vector2 value)
        {
            Write(value.X);
            Write(value.Y);
        }

        public void Write(Vector3 value)
        {
            Write(value.X);
            Write(value.Y);
            Write(value.Z);
        }

        public void Write(Vector4 value)
        {
            Write(value.X);
            Write(value.Y);
            Write(value.Z);
            Write(value.W);
        }

        public void Write(Matrix value)
        {
            Write(value.M11);
            Write(value.M12);
            Write(value.M13);
            Write(value.M14);

            Write(value.M21);
            Write(value.M22);
            Write(value.M23);
            Write(value.M24);

            Write(value.M31);
            Write(value.M32);
            Write(value.M33);
            Write(value.M34);

            Write(value.M41);
            Write(value.M42);
            Write(value.M43);
            Write(value.M44);
        }

        public void Write(VertexElement value)
        {
            Write(value.Offset);
            Write((int)value.VertexElementFormat);
            Write((int)value.VertexElementUsage);
            Write(value.UsageIndex);
        }

        public void Write(BoundingBox value)
        {
            Write(value.Min);
            Write(value.Max);
        }

        public void Write(Rectangle value)
        {
            Write(value.X);
            Write(value.Y);
            Write(value.Width);
            Write(value.Height);
        }

        public void WriteArray(short[] array)
        {
            Write(array.Length);
            for (int i = 0; i != array.Length; i++)
            {
                Write(array[i]);
            }
        }

        public void WriteArray(int[] array)
        {
            Write(array.Length);
            for (int i = 0; i != array.Length; i++)
            {
                Write(array[i]);
            }
        }

        public void WriteArray(float[] array)
        {
            Write(array.Length);
            for (int i = 0; i != array.Length; i++)
            {
                Write(array[i]);
            }
        }

        public void WriteArray(VertexElement[] array)
        {
            Write(array.Length);
            for (int i = 0; i != array.Length; i++)
            {
                Write(array[i]);
            }
        }

        public void WriteArray(Rectangle[] array)
        {
            Write(array.Length);
            for (int i = 0; i != array.Length; i++)
            {
                Write(array[i]);
            }
        }

        public void WriteArray<T>(T[] array)
        {
            Write(array.Length);
            for (int i = 0; i != array.Length; i++)
            {
                WriteObject<T>(array[i]);
            }
        }

        public void WriteVertexBuffer(VertexBufferContent vertexBuffer)
        {
            WriteArray(vertexBuffer.VertexElements);
            Write(vertexBuffer.VertexCount);
            WriteArray(vertexBuffer.Vertices.ToArray());
        }

        public void WriteIndexBuffer(IndexBufferContent indexBuffer)
        {
            Write(indexBuffer.Indices.Count);
            WriteArray(indexBuffer.Indices.ToArray());
        }

        public void WriteAnyObject(object value)
        {
            IContentTypeWriter typeWriter = Context.GetContentTypeWriterForType(value.GetType());

            Write(typeWriter.ContentReaderName());
            typeWriter.WriteObject(value, this);
        }

        public void WriteObject<T>(T value)
        {
            WriteAnyObject(value);
        }

        public void WriteExternalReference(ExternalReference reference)
        {
            Write(reference.ToURL());
        }
    }
}
